﻿#include<iostream>
using namespace std;

//int main()
//{
//	
//	//new对于内置类型就相当于malloc：new -> operator new -> malloc
//	//动态申请一个int类型的空间
//	int* a1 = new int;//默认不初始化
//	//动态申请一个int类型的空间，初始化为1
//	int* a2 = new int(1);
//	//动态申请十个int类型的空间并初始化前5个空间
//	int* a3 = new int[10]{1,2,3,4,5};
//
//	//delete对于内置类型就相当于free：delete -> operator delete ->free
//	delete a1;
//	delete a2;
//	//delete[] a3;
//	delete a3;//内置类型不加[]进行delete也可以
//
//	return 0;
//}

class A
{
public:

	A(int a1 = 0, int a2 = 0)
	{
		cout << "A()" << endl;
		_a1 = a1;
		_a2 = a2;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1;
	int _a2;
};


int main()
{
	//new对于自定义类型对象开辟空间时== operator new + 构造函数
	// operator new() == malloc()
	// 构造函数：初始化对象
	//当不显式实现构造函数时，编译器会优化不调用构造函数
	A* a1 = new A;
	A* a2 = new A(1,1);
 
	A* a3 = new A[10]{ {1,1},{2,2},{3,3},{4,4} };//隐式类型转换
	/*这里的{}中的数和[]中的数不匹配，这里就会调用默认构造函数
 如果没有默认构造就会报错*/
 
	A* a4 = new A[3]{ A(1),A(2),A(3) };//传匿名对象
 delete[] a4;
	//delete对于自定义类型对象就当于：析构函数 + operator delete
	//析构函数：先将对象指向的资源给清理
	//operator delete() == free()
	//当不显式实现析构函数时，编译器会优化不调用析构函数
	delete a1;

	delete a2;

	//delete[] a3;

	//new[]时也在a3指向空间前再开辟4个字节的空间，用于存放[]中的数字
	//用于提示要调用几次析构函数(显式实现的)
	
	delete a3;
	// 显式实现析构函数时，这种方式会导致从a3处开始释放资源，因为位置不对所以会报错
	// 而且因为不是从[]开辟的空间开始释放，所以也不知道要调用几次析构函数，可能会导致内存泄漏（但不会报错）
	//没有显式实现析构函数时，这样也可以实现
	return 0;
}
/////////////////////////////////////////////

//总结：在自定义类型对象new和delete关联的是构造函数和析构函数的调用次数





